package top.bug.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import top.bug.blog.common.BasePO;
import top.bug.blog.constant.CommonConstants;
import top.bug.blog.entity.dto.album.*;
import top.bug.blog.entity.dto.common.BatchRequest;
import top.bug.blog.entity.dto.common.OrderModRequest;
import top.bug.blog.entity.dto.common.SingleRequest;
import top.bug.blog.entity.po.Album;
import top.bug.blog.entity.po.AlbumPic;
import top.bug.blog.enums.ErrorCode;
import top.bug.blog.exception.BussinessException;
import top.bug.blog.mapper.AlbumMapper;
import top.bug.blog.mapper.AlbumPicMapper;
import top.bug.blog.service.AlbumService;
import top.bug.blog.utils.QueryWrapperUtils;
import top.bug.blog.utils.StrUtils;
import top.bug.blog.utils.UpYunUtil;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="https://github.com/jiusi66">九思.</a>
 * @email 10837907@qq.com
 * @from <a href="https://www.52bug.top">递归茶馆-www.52bug.top</a>
 * @description 相册 实现类
 */
@Service
@Slf4j
public class AlbumServiceImpl extends ServiceImpl<AlbumMapper, Album> implements AlbumService {
    @Resource
    private AlbumMapper albumMapper;
    @Resource
    private AlbumPicMapper albumPicMapper;

    @Override
    public Page<Album> getList(AlbumQueryRequest queryRequest) {
        if (null == queryRequest) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        Page<Album> page = new Page<>(queryRequest.getPageNum(), queryRequest.getPageSize());
        String name = queryRequest.getName();
        String status = queryRequest.getStatus();
        LambdaQueryWrapper<Album> queryWrapper = new LambdaQueryWrapper<Album>()
                .eq(StrUtils.isNotBlank(status), Album::getStatus, status)
                .like(StrUtils.isNotBlank(name), Album::getName, name)
                .or()
                .like(StrUtils.isNotBlank(name), Album::getDescription, name);
        // 时间范围参数
        QueryWrapperUtils.addTimeRangeCondition(queryWrapper, queryRequest.getCreateTimeRange(), Album::getCreateOn);
        QueryWrapperUtils.addTimeRangeCondition(queryWrapper, queryRequest.getUpdateTimeRange(), Album::getUpdateOn);
        // 定义允许排序的字段白名单
        Map<String, SFunction<Album, ?>> sortFields = new HashMap<>(3);
        sortFields.put("orderNum", Album::getOrderNum);
        sortFields.put("createOn", Album::getCreateOn);
        sortFields.put("imgCount", Album::getImgCount);
        // 添加安全排序
        QueryWrapperUtils.addSafeSort(queryWrapper, queryRequest.getSortField(), queryRequest.getSortOrder(), sortFields);
        albumMapper.selectPage(page, queryWrapper);
        return page;
    }

    @Override
    public Boolean add(AlbumAddRequest addRequest) {
        if (null == addRequest) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        // 必填项校验
        String name = addRequest.getName();
        String picUrl = addRequest.getPicUrl();
        if (StrUtils.isAnyBlank(name, picUrl)) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        Album album = new Album();
        BeanUtil.copyProperties(addRequest, album);
        // 默认值填充
        String status = addRequest.getStatus();
        if (StrUtil.isEmpty(status)) {
            album.setStatus(CommonConstants.STATUS_ENABLE);
        }
        if (null == addRequest.getOrderNum()) {
            album.setOrderNum(CommonConstants.DEFAULT_ORDER_NUM);
        }
        album.setImgCount(0);
        // 保存相册（唯一性由数据库层面进行控制）
        boolean save;
        try {
            save = this.save(album);
        } catch (DuplicateKeyException e) {
            throw new BussinessException(ErrorCode.DATA_ALREADY_EXISTED);
        }
        return save;
    }

    @Override
    public Boolean edit(AlbumUpdateRequest updateRequest) {
        if (null == updateRequest || StrUtil.isEmpty(updateRequest.getId())) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        Album album = new Album();
        BeanUtil.copyProperties(updateRequest, album);
        return this.updateById(album);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(BatchRequest batchRequest) {
        if (null == batchRequest || CollUtil.isEmpty(batchRequest.getIds())) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        List<String> ids = batchRequest.getIds();
        LambdaQueryWrapper<AlbumPic> queryWrapper = new LambdaQueryWrapper<AlbumPic>().in(AlbumPic::getAlbumId, ids);
        List<AlbumPic> list = albumPicMapper.selectList(queryWrapper);
        if (!list.isEmpty()) {
            // 删除相册下的所有图片(删除相册文件夹)
            for (AlbumPic albumPicPo : list) {
                String picUrl = albumPicPo.getPicUrl();
                String path = picUrl.substring(picUrl.lastIndexOf("/album"));
                try {
                    UpYunUtil.delete(path);
                } catch (Exception e) {
                    throw new BussinessException(ErrorCode.FILE_DELETE_ERROR);
                }
            }
            // 删除文件夹
            for (String id : ids) {
                try {
                    String dirPath = "/album/" + id + "/";
                    boolean b = UpYunUtil.delDir(dirPath);
                    if (!b) {
                        log.error("【{}】文件夹删除失败！", dirPath);
                    }
                } catch (Exception e) {
                    throw new BussinessException(ErrorCode.FILE_DELETE_ERROR);
                }
            }
            // 删除所有图片的数据库记录
            albumPicMapper.delete(queryWrapper);
        }
        // 删除相册
        return this.removeBatchByIds(ids);
    }

    @Override
    public Boolean editOrder(OrderModRequest modRequest) {
        if (null == modRequest) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        String id = modRequest.getId();
        Integer orderNum = modRequest.getOrderNum();
        if (StrUtil.isEmpty(id) || null == orderNum) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        LambdaUpdateWrapper<Album> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Album::getOrderNum, orderNum)
                .eq(BasePO::getId, id);
        return this.update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> uploadPic(AlbumUploadRequest uploadRequest) {
        if (null == uploadRequest) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        List<MultipartFile> files = uploadRequest.getFiles();
        String filePath = uploadRequest.getFilePath();
        String albumId = uploadRequest.getAlbumId();
        String path = filePath + albumId;
        ArrayList<String> res = new ArrayList<>();
        if (CollUtil.isEmpty(files) || StrUtil.isEmpty(albumId)) {
            return res;
        }
        for (MultipartFile file : files) {
            String fileName = file.getOriginalFilename();
            long size = file.getSize();
            // 查询图片名数量
            Long count = albumPicMapper.selectCount(new LambdaQueryWrapper<AlbumPic>()
                    .eq(AlbumPic::getAlbumId, albumId)
                    .eq(AlbumPic::getPicName, fileName)
            );
            if (count > 1) {
                fileName = fileName + "(" + (count - 1) + ")";
            }
            // 文件上传
            String url = "";
            try {
                url = UpYunUtil.upload(file, path);
                res.add(url);
            } catch (Exception e) {
                throw new BussinessException(ErrorCode.FILE_UPLOAD_ERROR);
            }
            // 插入数据库
            AlbumPic albumPicPo = new AlbumPic();
            albumPicPo.setPicName(fileName);
            albumPicPo.setPicSize(size);
            albumPicPo.setAlbumId(albumId);
            albumPicPo.setPicUrl(url);
            albumPicMapper.insert(albumPicPo);
        }
        // 更新相册图片数量
        albumMapper.modImgCount(albumId, res.size());
        return res;
    }

    @Override
    public List<AlbumPic> getPicList(SingleRequest singleRequest) {
        if (null == singleRequest || StrUtil.isEmpty(singleRequest.getId())) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        return albumPicMapper.selectList(
                new LambdaQueryWrapper<AlbumPic>().eq(AlbumPic::getAlbumId, singleRequest.getId()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletePic(BatchRequest batchRequest) {
        if (null == batchRequest || CollUtil.isEmpty(batchRequest.getIds())) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        List<AlbumPic> list = albumPicMapper.selectBatchIds(batchRequest.getIds());
        Map<String, Integer> count = new HashMap<>();
        for (AlbumPic albumPicPo : list) {
            String picUrl = albumPicPo.getPicUrl();
            String path = picUrl.substring(picUrl.lastIndexOf("/album"));
            try {
                UpYunUtil.delete(path);
            } catch (Exception e) {
                throw new BussinessException(ErrorCode.FILE_DELETE_ERROR);
            }
            // 记录删除文件数，更新相册图片数量
            String albumId = albumPicPo.getAlbumId();
            if (count.containsKey(albumId)) {
                count.put(albumId, count.get(albumId) + 1);
            } else {
                count.put(albumId, 1);
            }
        }
        // 删除数据库记录
        albumPicMapper.deleteByIds(batchRequest.getIds());
        // 更新相册图片数量
        count.forEach((k, v) -> {
            albumMapper.modImgCount(k, -v);
        });
        return true;
    }

    @Override
    public void renamePic(AlbumPicUpdateRequest updateRequest) {
        String id = updateRequest.getId();
        String newName = updateRequest.getNewName();
        if (StrUtils.isAnyBlank(id, newName)) {
            throw new BussinessException(ErrorCode.PARAM_NOT_COMPLETE);
        }
        // 同一个相册下不允许出现同名图片
        AlbumPic albumPic = albumPicMapper.selectById(id);
        String albumId = albumPic.getAlbumId();
        // 查询是否存在同名图片
        Long count = albumPicMapper.selectCount(new LambdaQueryWrapper<AlbumPic>()
                .eq(AlbumPic::getAlbumId, albumId)
                .ne(BasePO::getId, id)
                .eq(AlbumPic::getPicName, newName)
        );
        if (count > 0) {
            throw new BussinessException(ErrorCode.DATA_ALREADY_EXISTED, "已存在同名图片，请修改后提交！");
        }
        albumPicMapper.update(new LambdaUpdateWrapper<AlbumPic>()
                .eq(BasePO::getId, id)
                .set(AlbumPic::getPicName, newName)
        );
    }

}